using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Input;
using ScreenManagement;
using HexTileBoard;

namespace ScreenManagement
{
    /// <summary>
    /// The options screen is brought up over the top of the main menu
    /// screen, and gives the user a chance to configure the game
    /// in various hopefully useful ways.
    /// </summary>
    class OptionsMenuScreen : MenuScreen
    {
        #region Fields

        MenuEntry blueMenuEntry, redMenuEntry, yellowMenuEntry, greenMenuEntry;
        MenuEntry boardSize;
        MenuEntry terrainType;

        enum PlayerType : short
        {
            Local,
            AI,
            Closed,
        }

        int numLocalPlayers = 0, numAIPlayers = 0;

        PlayerType bluePlayer = PlayerType.Local, redPlayer = PlayerType.Local, greenPlayer = PlayerType.Closed, yellowPlayer = PlayerType.Closed;
        BoardSize currentSize = BoardSize.Medium;

        // Track the player indices and whether we need to look for them when starting the game
        PlayerColor retrievingIndexFor = PlayerColor.None;
        PlayerIndex? blueIndex = null, redIndex = null, greenIndex = null, yellowIndex = null;
        bool needBlue = true, needRed = true, needGreen = false, needYellow = false;

        // Hint items
        private SpriteBatch spriteBatch;
        private SpriteFont spriteFont;
        private Texture2D gradient;
        string selectedHint = "Hint: " + BoardVariables.GameHints[BoardConstructor.random.Next(0, BoardVariables.GameHints.Length)];

        #endregion

        #region Initialization


        /// <summary>
        /// Constructor.
        /// </summary>
        public OptionsMenuScreen()
            : base("Options")
        {
            // Create our menu entries.
            blueMenuEntry = new MenuEntry(string.Empty);
            redMenuEntry = new MenuEntry(string.Empty);
            greenMenuEntry = new MenuEntry(string.Empty);
            yellowMenuEntry = new MenuEntry(string.Empty);
            boardSize = new MenuEntry(string.Empty);

            SetMenuEntryText();

            MenuEntry start = new MenuEntry("Start");
            MenuEntry back = new MenuEntry("Back");

            // Hook up menu event handlers.
            blueMenuEntry.Selected += BlueMenuEntrySelected;
            redMenuEntry.Selected += RedMenuEntrySelected;
            greenMenuEntry.Selected += GreenMenuEntrySelected;
            yellowMenuEntry.Selected += YellowMenuEntrySelected;
            boardSize.Selected += BoardSizeMenuEntrySelected;
            start.Selected += PlayGameMenuEntrySelected;
            back.Selected += OnCancel;
            
            // Add entries to the menu.
            MenuEntries.Add(blueMenuEntry);
            MenuEntries.Add(redMenuEntry);
            MenuEntries.Add(greenMenuEntry);
            MenuEntries.Add(yellowMenuEntry);
            MenuEntries.Add(boardSize);
            MenuEntries.Add(start);
            MenuEntries.Add(back);
        }

        public override void LoadContent()
        {
            base.LoadContent();

            // Load font for drawing hint
            spriteBatch = new SpriteBatch(this.ScreenManager.GraphicsDevice);

            ContentManager content = new ContentManager(this.ScreenManager.Game.Services, "Content");
            spriteFont = content.Load<SpriteFont>("Fonts/gameFontSmall");
            gradient = content.Load<Texture2D>("Textures/Screens/gradient");
        }


        /// <summary>
        /// Fills in the latest values for the options screen menu text.
        /// </summary>
        void SetMenuEntryText()
        {
            blueMenuEntry.Text = "Blue Team: " + bluePlayer;
            redMenuEntry.Text = "Red Team: " + redPlayer;
            greenMenuEntry.Text = "Green Team: " + greenPlayer;
            yellowMenuEntry.Text = "Yellow Team: " + yellowPlayer;
            boardSize.Text = "Size: " + currentSize;

            numLocalPlayers = 0;
            numAIPlayers = 0;

            if (bluePlayer == PlayerType.Local)
            {
                needBlue = true;
                numLocalPlayers++;
            }
            else
            {
                needBlue = false;
                if (bluePlayer == PlayerType.AI)
                    numAIPlayers++;
            }

            if (redPlayer == PlayerType.Local)
            {
                needRed = true;
                numLocalPlayers++;
            }
            else
            {
                needRed = false;
                if (redPlayer == PlayerType.AI)
                    numAIPlayers++;
            }

            if (yellowPlayer == PlayerType.Local)
            {
                needYellow = true;
                numLocalPlayers++;
            }
            else
            {
                needYellow = false;
                if (yellowPlayer == PlayerType.AI)
                    numAIPlayers++;
            }

            if (greenPlayer == PlayerType.Local)
            {
                needGreen = true;
                numLocalPlayers++;
            }
            else
            {
                needGreen = false;
                if (greenPlayer == PlayerType.AI)
                    numAIPlayers++;
            }
        }

        public override void Draw(GameTime gameTime)
        {
            base.Draw(gameTime);

            // Draw hint
            spriteBatch.Begin();
            spriteBatch.Draw(gradient, new Rectangle(0, this.ScreenManager.GraphicsDevice.Viewport.Bounds.Height - 160, this.ScreenManager.GraphicsDevice.Viewport.Bounds.Width, 120), new Color(0.5f, 0.5f, 0.5f, 0.5f));
            spriteBatch.DrawString(spriteFont, selectedHint, new Vector2((this.ScreenManager.GraphicsDevice.Viewport.Bounds.Width / 2) - (spriteFont.MeasureString(selectedHint).X / 2), this.ScreenManager.GraphicsDevice.Viewport.Bounds.Height - 140), Color.White);
            spriteBatch.End();

        }

        #endregion

        #region Handle Input


        /// <summary>
        /// Event handler for when the Ungulate menu entry is selected.
        /// </summary>
        void BlueMenuEntrySelected(object sender, PlayerIndexEventArgs e)
        {
            bluePlayer++;

            if (bluePlayer > PlayerType.Closed)
                bluePlayer = 0;

            SetMenuEntryText();
        }

        void RedMenuEntrySelected(object sender, PlayerIndexEventArgs e)
        {
            redPlayer++;

            if (redPlayer > PlayerType.Closed)
                redPlayer = 0;

            SetMenuEntryText();
        }

        void GreenMenuEntrySelected(object sender, PlayerIndexEventArgs e)
        {
            greenPlayer++;

            if (greenPlayer > PlayerType.Closed)
                greenPlayer = 0;

            SetMenuEntryText();
        }

        void YellowMenuEntrySelected(object sender, PlayerIndexEventArgs e)
        {
            yellowPlayer++;

            if (yellowPlayer > PlayerType.Closed)
                yellowPlayer = 0;

            SetMenuEntryText();
        }

        /// <summary>
        /// Event handler for when the Language menu entry is selected.
        /// </summary>
        void BoardSizeMenuEntrySelected(object sender, PlayerIndexEventArgs e)
        {
            switch (currentSize)
            {
                case BoardSize.Tiny:
                    currentSize = BoardSize.Small; break;
                case BoardSize.Small:
                    currentSize = BoardSize.Medium; break;
                case BoardSize.Medium:
                    currentSize = BoardSize.Big; break;
                case BoardSize.Big:
                    currentSize = BoardSize.Huge; break;
                case BoardSize.Huge:
                    currentSize = BoardSize.Tiny; break;
            }

            SetMenuEntryText();
        }

        /// <summary>
        /// Event handler for when the Play Game menu entry is selected.
        /// </summary>
        void PlayGameMenuEntrySelected(object sender, PlayerIndexEventArgs e)
        {
            bool cont = true;
#if XBOX
            if ((currentSize > BoardSize.Medium) && Guide.IsTrialMode)
            {
                cont = false;

                SignedInGamer gamer = Gamer.SignedInGamers[(PlayerIndex)ControllingPlayer];
                if (gamer != null)
                {
                    if (gamer.Privileges.AllowPurchaseContent)
                    {
                        Guide.ShowMarketplace((PlayerIndex)ControllingPlayer);
                    }
                    else
                    {
                        MessageBoxScreen useAllowContentBox = new MessageBoxScreen("Please use an account with purchase privileges\nto play this version!");
                        ScreenManager.AddScreen(useAllowContentBox, ControllingPlayer);
                    }
                }
                else
                {
                    //sign in and purchase message box
                    //Guide.ShowSignIn(1, false);
                    MessageBoxScreen signInBox = new MessageBoxScreen("Please sign in to an account with purchase privileges\nto play this version!");
                    ScreenManager.AddScreen(signInBox, ControllingPlayer);
                }
            }
#endif
            if (cont == false)
                return;

            if (numLocalPlayers == 1)
            {
                // override PC variables
#if XBOX
                LoadingScreen.Load(ScreenManager, true, this.ControllingPlayer, 
                    new GameplayScreen(null, bluePlayer == PlayerType.AI, bluePlayer == PlayerType.Local ? this.ControllingPlayer : null,
                        redPlayer == PlayerType.AI, redPlayer == PlayerType.Local ? this.ControllingPlayer : null,
                        greenPlayer == PlayerType.AI, greenPlayer == PlayerType.Local ? this.ControllingPlayer : null,
                        yellowPlayer == PlayerType.AI, yellowPlayer == PlayerType.Local ? this.ControllingPlayer : null,
                        currentSize));
#else
                if (needBlue) blueIndex = PlayerIndex.One;
                if (needRed) redIndex = PlayerIndex.Two;
                if (needGreen) greenIndex = PlayerIndex.Three;
                if (needYellow) yellowIndex = PlayerIndex.Four;
                LoadingScreen.Load(ScreenManager, true, this.ControllingPlayer,
                    new GameplayScreen(null, bluePlayer == PlayerType.AI, blueIndex,
                        redPlayer == PlayerType.AI, redIndex,
                        greenPlayer == PlayerType.AI, greenIndex,
                        yellowPlayer == PlayerType.AI, yellowIndex,
                        currentSize));
#endif
            }
            else    // Mutiple controllers must be marshalled in
            {
                // Assign the controlling index to the first available player in b/r/g/y order and then continue in same
                string assignedMessage = "";
                if (needBlue)
                {
                    blueIndex = this.ControllingPlayer;
                    assignedMessage = "Blue has controller " + this.ControllingPlayer.Value.ToString() + ".\n";
                }
                else if (needRed)
                {
                    redIndex = this.ControllingPlayer;
                    assignedMessage = "Red has controller " + this.ControllingPlayer.Value.ToString() + ".\n";
                }
                else if (needGreen)
                {
                    greenIndex = this.ControllingPlayer;
                    assignedMessage = "Green has controller " + this.ControllingPlayer.Value.ToString() + ".\n";
                }
                else if (needYellow)
                {
                    yellowIndex = this.ControllingPlayer;
                    assignedMessage = "Yellow has controller " + this.ControllingPlayer.Value.ToString() + ".\n";
                }

                // Get the remaining players, as blue will always at the least be checked first
                if (needRed && redIndex == null)
                {
                    retrievingIndexFor = PlayerColor.Red;
                    MessageBoxScreen secondPlayerMessageBox = new MessageBoxScreen(assignedMessage + "Please hit 'A' on the the red player's controller:");
                    secondPlayerMessageBox.Accepted += ConfirmMessageBoxAccepted;
                    secondPlayerMessageBox.Cancelled += ConfirmMessageBoxRejected;
                    ScreenManager.AddScreen(secondPlayerMessageBox, null);
                }
                else if (needGreen && greenIndex == null)
                {
                    retrievingIndexFor = PlayerColor.Green;
                    MessageBoxScreen secondPlayerMessageBox = new MessageBoxScreen(assignedMessage + "Please hit 'A' on the the green player's controller:");
                    secondPlayerMessageBox.Accepted += ConfirmMessageBoxAccepted;
                    secondPlayerMessageBox.Cancelled += ConfirmMessageBoxRejected;
                    ScreenManager.AddScreen(secondPlayerMessageBox, null);
                }
                else if (needYellow && yellowIndex == null)
                {
                    retrievingIndexFor = PlayerColor.Yellow;
                    MessageBoxScreen secondPlayerMessageBox = new MessageBoxScreen(assignedMessage + "Please hit 'A' on the the yellow player's controller:");
                    secondPlayerMessageBox.Accepted += ConfirmMessageBoxAccepted;
                    secondPlayerMessageBox.Cancelled += ConfirmMessageBoxRejected;
                    ScreenManager.AddScreen(secondPlayerMessageBox, null);
                }
            }
        }

        public override void HandleInput(GameTime _gameTime, InputState input)
        {
            if (input.IsNewButtonPress(Buttons.LeftShoulder, this.ControllingPlayer.Value) || 
                input.IsNewButtonPress(Buttons.LeftTrigger, this.ControllingPlayer.Value) || 
                //input.IsNewButtonPress(Buttons.LeftThumbstickLeft, this.ControllingPlayer.Value) ||
                //input.IsNewButtonPress(Buttons.RightThumbstickLeft, this.ControllingPlayer.Value) ||
                input.IsNewButtonPress(Buttons.DPadLeft, this.ControllingPlayer.Value) ||
                input.IsNewKeyPress(Keys.Left, this.ControllingPlayer.Value))
            {
                switch (this.SelectedEntry)
                {
                    case 0:
                        bluePlayer--;
                        if (bluePlayer < 0)
                            bluePlayer = PlayerType.Closed;
                        break;
                    case 1:
                        redPlayer--;
                        if (redPlayer < 0)
                            redPlayer = PlayerType.Closed;
                        break;
                    case 2:
                        greenPlayer--;
                        if (greenPlayer < 0)
                            greenPlayer = PlayerType.Closed;
                        break;
                    case 3:
                        yellowPlayer--;
                        if (yellowPlayer < 0)
                            yellowPlayer = PlayerType.Closed;
                        break;
                    case 4:
                        switch (currentSize)
                        {
                            case BoardSize.Tiny:
                                currentSize = BoardSize.Huge; break;
                            case BoardSize.Small:
                                currentSize = BoardSize.Tiny; break;
                            case BoardSize.Medium:
                                currentSize = BoardSize.Small; break;
                            case BoardSize.Big:
                                currentSize = BoardSize.Medium; break;
                            case BoardSize.Huge:
                                currentSize = BoardSize.Big; break;
                        }
                        break;
                }

                SetMenuEntryText();
            }
            else if (input.IsNewButtonPress(Buttons.RightShoulder, this.ControllingPlayer.Value) ||
                input.IsNewButtonPress(Buttons.RightTrigger, this.ControllingPlayer.Value) ||
                //input.IsNewButtonPress(Buttons.LeftThumbstickRight, this.ControllingPlayer.Value) ||
                //input.IsNewButtonPress(Buttons.RightThumbstickRight, this.ControllingPlayer.Value) ||
                input.IsNewButtonPress(Buttons.DPadRight, this.ControllingPlayer.Value) ||
                input.IsNewKeyPress(Keys.Right, this.ControllingPlayer.Value))
            {
                switch (this.SelectedEntry)
                {
                    case 0:
                        bluePlayer++;
                        if (bluePlayer > PlayerType.Closed)
                            bluePlayer = 0;
                        break;
                    case 1:
                        redPlayer++;
                        if (redPlayer > PlayerType.Closed)
                            redPlayer = 0;
                        break;
                    case 2:
                        greenPlayer++;
                        if (greenPlayer > PlayerType.Closed)
                            greenPlayer = 0;
                        break;
                    case 3:
                        yellowPlayer++;

                        if (yellowPlayer > PlayerType.Closed)
                            yellowPlayer = 0;
                        break;
                    case 4:
                        switch (currentSize)
                        {
                            case BoardSize.Tiny:
                                currentSize = BoardSize.Small; break;
                            case BoardSize.Small:
                                currentSize = BoardSize.Medium; break;
                            case BoardSize.Medium:
                                currentSize = BoardSize.Big; break;
                            case BoardSize.Big:
                                currentSize = BoardSize.Huge; break;
                            case BoardSize.Huge:
                                currentSize = BoardSize.Tiny; break;
                        }
                        break;
                }

                SetMenuEntryText();
            }
            else if (input.CurrentKeyboardStates[(int)this.ControllingPlayer].IsKeyDown(Microsoft.Xna.Framework.Input.Keys.Back) || input.CurrentGamePadStates[(int)this.ControllingPlayer].IsButtonDown(Microsoft.Xna.Framework.Input.Buttons.B) || input.CurrentGamePadStates[(int)this.ControllingPlayer].IsButtonDown(Microsoft.Xna.Framework.Input.Buttons.Back))
            {
                //this.ScreenManager.currentBackground = 0;
                this.ExitScreen();
            }

            base.HandleInput(_gameTime, input);
        }

        // Get the rest of the necessary indices. Blue will always be checked before entry, so do not need to check here.
        void ConfirmMessageBoxAccepted(object sender, PlayerIndexEventArgs e)
        {
            string assignedMessage = "";

            switch (retrievingIndexFor)
            {
                case PlayerColor.Red:
                    redIndex = e.PlayerIndex; 
                    assignedMessage = "Red has controller " + e.PlayerIndex.ToString() + ".\n";break;
                case PlayerColor.Green:
                    greenIndex = e.PlayerIndex;
                    assignedMessage = "Green has controller " + e.PlayerIndex.ToString() + ".\n";break;
                case PlayerColor.Yellow:
                    yellowIndex = e.PlayerIndex; 
                    assignedMessage = "Yellow has controller " + e.PlayerIndex.ToString() + ".\n";break;
            }

            if (needRed && redIndex == null)
            {
                retrievingIndexFor = PlayerColor.Red;
                MessageBoxScreen secondPlayerMessageBox = new MessageBoxScreen(assignedMessage + "Please hit 'A' on the the red player's controller:");
                secondPlayerMessageBox.Accepted += ConfirmMessageBoxAccepted;
                secondPlayerMessageBox.Cancelled += ConfirmMessageBoxRejected;
                ScreenManager.AddScreen(secondPlayerMessageBox, null);
            }
            else if (needGreen && greenIndex == null)
            {
                retrievingIndexFor = PlayerColor.Green;
                MessageBoxScreen secondPlayerMessageBox = new MessageBoxScreen(assignedMessage + "Please hit 'A' on the the green player's controller:");
                secondPlayerMessageBox.Accepted += ConfirmMessageBoxAccepted;
                secondPlayerMessageBox.Cancelled += ConfirmMessageBoxRejected;
                ScreenManager.AddScreen(secondPlayerMessageBox, null);
            }
            else if (needYellow && yellowIndex == null)
            {
                retrievingIndexFor = PlayerColor.Yellow;
                MessageBoxScreen secondPlayerMessageBox = new MessageBoxScreen(assignedMessage + "Please hit 'A' on the the yellow player's controller:");
                secondPlayerMessageBox.Accepted += ConfirmMessageBoxAccepted;
                secondPlayerMessageBox.Cancelled += ConfirmMessageBoxRejected;
                ScreenManager.AddScreen(secondPlayerMessageBox, null);
            }
            
            if (((needBlue && blueIndex != null) || !needBlue) &&
                ((needRed && redIndex != null) || !needRed) &&
                ((needGreen && greenIndex != null) || !needGreen) &&
                ((needYellow && yellowIndex != null) || !needYellow))
            {
#if XBOX
                LoadingScreen.Load(ScreenManager, true, this.ControllingPlayer,
                        new GameplayScreen(null, bluePlayer == PlayerType.AI, blueIndex,
                            redPlayer == PlayerType.AI, redIndex,
                            greenPlayer == PlayerType.AI, greenIndex,
                            yellowPlayer == PlayerType.AI, yellowIndex,
                            currentSize));
#else
                // override PC variables
                if (blueIndex != null) blueIndex = PlayerIndex.One;
                if (redIndex != null) redIndex = PlayerIndex.Two;
                if (greenIndex != null) greenIndex = PlayerIndex.Three;
                if (yellowIndex != null) yellowIndex = PlayerIndex.Four;
                LoadingScreen.Load(ScreenManager, true, this.ControllingPlayer,
                    new GameplayScreen(null, bluePlayer == PlayerType.AI, blueIndex,
                        redPlayer == PlayerType.AI, redIndex,
                        greenPlayer == PlayerType.AI, greenIndex,
                        yellowPlayer == PlayerType.AI, yellowIndex,
                        currentSize));
#endif
            }
        }

        // reset the indices
        void ConfirmMessageBoxRejected(object sender, PlayerIndexEventArgs e)
        {
            blueIndex = redIndex = greenIndex = yellowIndex = null;
        }

        #endregion
    }
}
